
//Copyright 1997-2009 Syrinx Development, Inc.
//This file is part of the Syrinx Web Application Framework (SWAF).
// == BEGIN LICENSE ==
//
// Licensed under the terms of any of the following licenses at your
// choice:
//
//  - GNU General Public License Version 3 or later (the "GPL")
//    http://www.gnu.org/licenses/gpl.html
//
//  - GNU Lesser General Public License Version 3 or later (the "LGPL")
//    http://www.gnu.org/licenses/lgpl.html
//
//  - Mozilla Public License Version 1.1 or later (the "MPL")
//    http://www.mozilla.org/MPL/MPL-1.1.html
//
// == END LICENSE ==
using System;
using System.Collections;
using System.Text;
using System.Xml;

using Swaf;
using Swaf.BizObj;
using Swaf.Container;
using Swaf.Security;

namespace Swaf.Security
{
	/// <summary>
	/// Implements the IPartneredResourceSet to work in conjuntion with an 
	/// IResourceSetPartner object that will assist this class with maintaining
	/// its collection of resources.  This class can call to the IPartneredResource
	/// set to get its collection of resources or the IPartneredResourceSet can
	/// push changes into this object as it sees changes to the resources held
	/// within it.</summary>
    [Serializable]
	class PartneredResourceSet : IPartneredResourceSet
    {
		/// <summary>
		/// The name of this resource set as needed by the IResourceSet interface.
		/// </summary>
        protected string m_name;
		/// <summary>
		/// The partner object that will get the list of resources for this 
		/// when needed.</summary>
        [NonSerialized] protected IResourceSetPartner m_dataPartner;
		/// <summary>
		/// Maintains if this has been initially populated with resources as
		/// needed by the IResourceSet interface.</summary>
        protected bool m_isPopulated = false;

		/// <summary>
		/// The resources that exist for this at any given time.  This collection
		/// can change dynamically.</summary>
        protected INameAddressSupport m_resources = null;
        protected string m_resourceCallXml;

		/// <summary>
		/// This is the main way to create an instance of this class.  The element tells
		/// this resource set what its name is and where to find its config partner
		/// in the AOM.</summary>
		/// <param name="configuration">The XmlElement with the needed information
		/// this can optionally contain 2 attributes
		/// name - the name of the resource set.
		/// configPartnerPath - the location in the AOM of this object's config partner</param>
        public PartneredResourceSet(XmlElement configuration)
        {
			try
			{
				m_name = configuration.GetAttribute("name");
				string path = configuration.GetAttribute("configPartnerPath");
				if (path != null && path.Length > 0)
				{
					int index = path.IndexOf('.');
					string baseName = path.Substring(0, index).ToLower();
					if (baseName == "app")
						m_dataPartner = (IResourceSetPartner)Application.currentApp.appData.get(path.Substring(index + 1));
					else if (baseName == "session")
						m_dataPartner = (IResourceSetPartner)Application.currentApp.sessionData.get(path.Substring(index + 1));
					else
						throw new BaseSecurityException(
							String.Format("If configPartnerPath is specified it must start with 'app' or 'session'.  The invalid value is: {0}",
							path));
                    populateResources();
				}
			}
			catch (BaseSecurityException)
			{
				throw;
			}
			catch (Exception e)
			{
				throw new BaseSecurityException("Error processing XmlElement configuration", e);
			}

        }

		/// <summary>
		/// Used by clone to make a copy of an instance</summary>
		/// <param name="copy"></param>
        protected PartneredResourceSet(PartneredResourceSet copy)
        {
            m_name = copy.m_name;
            m_dataPartner = copy.m_dataPartner;
        }

        public IResourceSetPartner ResourceSetPartner
        {
            get { return m_dataPartner; }
            set {m_dataPartner = value;}
        }

        #region IResourceSet Members

		/// <summary>
		/// Creates a new instances of this resource set
		/// </summary>
		/// <returns></returns>
        public IResourceSet clone()
        {
            IResourceSet c = new PartneredResourceSet(this);
            return c;
        }

		public IResourceSet clone(bool deep)
		{
			return clone();
		}

        public bool isPopulated
        {
            get{return m_isPopulated;}
        }

        public string name
        {
            get { return m_name; }
        }

        public void populateResources()
        {
            if (m_dataPartner!=null)
            {
                m_dataPartner.updateResources(this, Application.currentApp.securityMgr.currentPrincipal);
                m_isPopulated = true;
            }
        }
        public void populateResources(INameAddressSupport additionalInfo)
        {
            populateResources();            
        }

        public INameAddressSupport populateResourcesFromList(IEnumerable source)
        {
            return this;
        }

        /// <summary>
        /// This method is not implemented for this class because it gets its resource from its IResourcePartner
        /// </summary>
        public Swaf.Call.ICall resourceCall
        {
            get {return null;}
        }


        /// <summary>
        /// 
        /// </summary>
        public string resourceCallXml
        {
            get { return m_resourceCallXml; }
            set { m_resourceCallXml = value; }
        }

        /// <summary>
        /// This method is not implemented for this class because it gets its resource from its IResourcePartner
        /// </summary>
        public Swaf.Container.INameAddressSupport resources
        {
            get {
                if (!isPopulated)
                    populateResources();
                return m_resources; 
            }
        }
        /// <summary>
        /// <see cref="IResourceSet.getBizObjList"/>
        /// </summary>
        public IBizObjList getBizObjList()
        {
            IBizObjList list = null;
            FlexiMap resourceList = (FlexiMap)m_resources;
            foreach (IResource rsc in resourceList)
            {
                IBizObj inst = rsc.bizObj;
                if (inst != null)
                {
                    if (list == null)
                    {
                        list = Application.currentApp.bizObjMgr.createList(inst.type.Name);
                    }
                    list.Add(inst);
                }
            }
            return list;
        }

        #endregion

        #region INameAddressSupport Members

        public Swaf.Container.XmlSerializationSupport SerializationSupport
        {
            get { return XmlSerializationSupport.AsElement; }
        }

        public string Xml
        {
            get { return ""; }
        }

        public bool containsField(string nameAddress)
        {
            if (!isPopulated)
                populateResources();
            return m_resources.containsField(nameAddress);
        }

        public object get(string nameAddress)
        {
			if (nameAddress == null)
				return this;
			if (!isPopulated)
                populateResources();
			object v = m_resources.get(nameAddress);
			if (v == null)
				v = m_resources.get("DefaultPrivilege");
			return v;
        }

        public object get(string nameAddress, object oneArg)
        {
			if (nameAddress == null)
				return this;
			if (!isPopulated)
                populateResources();
			object v = m_resources.get(nameAddress, oneArg);
			if (v == null && (oneArg == null || (oneArg is bool && (bool)oneArg)))
				v = m_resources.get("DefaultPrivilege");
			else if(v == null)
				v = Privileges.NotSet;
			return v;
        }

        public object get(string nameAddress, params object[] infoArgs)
        {
			if (nameAddress == null)
				return this;
			if (!isPopulated)
				populateResources();
			object v = m_resources.get(nameAddress);
			if (v == null && (infoArgs== null || infoArgs.Length == 0 || infoArgs[0] == null || (infoArgs[0] is bool && (bool)infoArgs[0])))
				v = m_resources.get("DefaultPrivilege");
			else if (v == null)
				v = Privileges.NotSet;
			return v;
		}

        public string getXml(string options)
        {
            return "";
        }

        public bool isGetOnly
        {
            get { return false; }
        }

        public void put(string nameAddress, object val, object extraInfo)
        {
        }

        public void put(string nameAddress, object val)
        {
        }

        #endregion

        #region IPartneredResourceSet Members

        public void resetResources(INameAddressSupport newResources)
        {
            m_resources = newResources;
        }

        #endregion
		public IEnumerator GetEnumerator() { return null; }
    }
}
